package com.spring.boot.reflect;

import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 自定义注解
 */
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyFactory{
    public String name() default "he";
    public String val();
}

class Book{
    private String name;
    private String pric;

    public Book() {}

    public String getBook(){
        return this.name + this.pric;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPric() {
        return pric;
    }

    public void setPric(String pric) {
        this.pric = pric;
    }

    public Book(String name, String pric) {
        this.name = name;
        this.pric = pric;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", pric='" + pric + '\'' +
                '}';
    }
}

@MyFactory(val = "hello")
public class MyAnnotation {
    public static void main(String[] args) throws Exception{
        Class<?> aClass = Class.forName("com.spring.boot.reflect.MyAnnotation");

        //得到注解
        Annotation[] annotations = aClass.getAnnotations();
        for (int i=0;i<annotations.length;i++) {
            System.out.println(annotations[i]);
        }

        //得到注解中值
        MyFactory an = aClass.getAnnotation(MyFactory.class);
        System.out.println(an.name());
        System.out.println(an.val());

        Class<?> bo = Class.forName("com.spring.boot.reflect.Book");
        //取得有参的构造
        Constructor<?> cons = bo.getConstructor(String.class,String.class);
        //调用的类最好有一个无参构造和全参构造，不然很麻烦
        Book book = (Book)cons.newInstance("java","88");
        System.out.println(book);

        Class<?> cls = Class.forName("com.spring.boot.reflect.Book");
        //取得名为name的成员变量
        Field name = cls.getDeclaredField("name");
        Object o = cls.newInstance();
        Method setName = cls.getMethod("setName", name.getType());
        Method setPric = cls.getMethod("setPric", name.getType());
        Method get = cls.getMethod("toString");

        setName.invoke(o,"何人");
        setPric.invoke(o,"12");

        //取得成员变量后可以直接赋值，但不推荐
        name.setAccessible(true);//可以给私有变量赋值
        name.set(o,"哈哈");

        System.out.println(get.invoke(o));

    }
}
